/*
 * Copyright (c) 2019. André Mion
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.andremion.floatingnavigationview;

import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * FloatButton浮动按钮
 *
 * @author hw
 * @since 2021/5/24
 */
public class FloatingNavigationView extends Component implements Component.DrawTask, AnimatorValue.ValueUpdateListener {
    private Paint paint;
    private AnimatorValue animatorValueTranslate;
    private AnimatorValue animatorValueRotate;
    private float animatorPercentTranslate;
    private float animatorPercentRotate;
    private boolean isOpen;
    private AnimatorGroup animatorGroup;
    private long animateDuration = 200;

    /**
     * Instantiates a new Float button.
     *
     * @param context the context
     * @param attrSet the attr set
     */
    public FloatingNavigationView(Context context, AttrSet attrSet) {
        super(context, attrSet, null);
        initPaint();
        initAnimator();
    }

    /**
     * Instantiates a new Float button.
     *
     * @param context   the context
     * @param attrSet   the attr set
     * @param styleName the style name
     */
    public FloatingNavigationView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {
        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setStyle(Paint.Style.FILL_STYLE);
        paint.setAntiAlias(true);
        addDrawTask(this);
    }

    /**
     * 初始化动画
     */
    private void initAnimator() {
        animatorGroup = new AnimatorGroup();
        animatorValueTranslate = new AnimatorValue();
        animatorValueTranslate.setDuration(animateDuration);
        animatorValueTranslate.setLoopedCount(0);
        animatorValueTranslate.setValueUpdateListener(this);

        animatorValueRotate = new AnimatorValue();
        animatorValueRotate.setDuration(animateDuration);
        animatorValueRotate.setLoopedCount(0);
        animatorValueRotate.setValueUpdateListener(this);
    }

    @Override
    public void addDrawTask(DrawTask task) {
        super.addDrawTask(task);
        task.onDraw(this, mCanvasForTaskOverContent);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        // 控件的高度等分
        int divideNum = 19;
        float translateX = (float) getWidth() / 2;
        float translateY = (float) getHeight() / divideNum;
        float centerY = (float) getHeight() / 2;
        for (int i = 0; i < 3; i++) {
            canvas.save();
            if (i != 1) {
                canvas.rotate((i == 0 ? 45 : -45) * animatorPercentRotate, translateX, centerY);
                canvas.translate(0, (i == 0 ? translateY : -translateY) * 2 * animatorPercentTranslate);
            } else if (animatorPercentRotate > 0) {
                // 第0根线和第2根线开始旋转之后，跳过draw第1根线，使close状态没有中间的线
                continue;
            }
            RectFloat rectF = new RectFloat(translateX / 2, translateY * (i * 2 + (float) (divideNum / 2 - 2)),
                    (float) (translateX * 1.5), translateY * (i * 2 + (float) (divideNum / 2 - 1)));
            canvas.drawRoundRect(rectF, 5, 5, paint);
            canvas.restore();
        }
    }

    /**
     * 改变打开/关闭状态
     *
     * @param isOpen 状态
     */
    public void changeState(boolean isOpen) {
        this.isOpen = isOpen;
        animatorGroup.cancel();
        if (isOpen) {
            animatorGroup.runSerially(animatorValueRotate, animatorValueTranslate);  // close状态下先旋转再位移
        } else {
            animatorGroup.runSerially(animatorValueTranslate, animatorValueRotate);  // open状态下先位移再旋转
        }
        animatorGroup.start();
    }

    @Override
    public void onUpdate(AnimatorValue animatorValue, float value) {
        if (animatorValue.equals(animatorValueTranslate)) {
            animatorPercentTranslate = isOpen ? 1f - value : value;
        } else {
            animatorPercentRotate = isOpen ? 1f - value : value;
        }
        invalidate();
    }

    /**
     * Sets animate duration.
     *
     * @param animateDuration the animate duration
     */
    public void setAnimateDuration(long animateDuration) {
        this.animateDuration = animateDuration;
    }
}